Latest update: July 2013
In this tutorial, we will show you how to poll your FlashAir device contents and make your content list auto refresh. We will use thumbnail.cgi and command.cgi to do this.
We will set the content list we created in Android Tutorial 4: Getting Image Thumbnails to regularly check if the contents of the FlashAir have changed. If they have changed, the content list will update itself. This tutorial will take some of the commands learned in previous tutorials and use them to obtain or display data.
Note: To get the most out of this tutorial, we suggest that you insert your FlashAir device into a digital camera. When you take a new photo or delete a photo, this application will show the changed contents of the FlashAir device.
The list containing the file name and thumbnail pairs of the contents of your FlashAir device will be formatted like this:
If you insert your FlashAir device into a digital camera and take a photograph, the content list will refresh itself (after a designated interval of time) and will include the photo that you just took:
You will be able to click the name of the new image file and view the photo in a new screen:
As you are viewing the image, the image file will download to your Android device.
We will need to create the following files in order to write this application:
Important: Please note that your project contains a
file called
AndroidManifest.xml. This file gives your application particular permissions. By
default,
applications are not permitted to access the internet. The path to this file should look
something
like:
[Project_Folder]/AndroidManifest.xml
You will need to add the following lines of code into your
AndroidManifest.xml in order for this application to work:
<uses-permission android:name="android.permission.INTERNET" />
First, we will write the activity_main.xml file that determines the layout of our Android App. This can be found in your layout folder. The path to this file should look something like: [Project_Folder]/res/layout/activity_main.xml
This file will be identical to the activity_main.xml file from Android Tutorial 3: Downloading Content. Please refer to that tutorial for an explanation of the implementation.
Next, we will create the activity_image_view.xml file that determines the layout of our image viewing screen. This can also be found in your layout folder. The path to this file should look something like: [Project_Folder]/res/layout/activity_image_view.xml
This file will be identical to the activity_image_view.xml file from Android Tutorial 3: Downloading Content. Please refer to that tutorial for an explanation of the implementation.
First, we will get a list of the file names in the desired directory of your FlashAir device (see Android Tutorial 3: Downloading Content for a detailed explanation).
Then we will set each file name in the list to an associated thumbnail, display both the
file name
and thumbnail pair in a
ListView
format, and set the behavior of the list. For detailed explanation on
the implementation,
see
Android Tutorial 4: Getting Image Thumbnails
Please take the MainActivity.java code from Android Tutorial 4: Getting Image Thumbnails and copy it into your new MainActivity.java file.
We will replace the
class MainActivity
declaration, member variables, and
onCreate(Bundle savedInstanceState)
function with the code below:
public class MainActivity extends Activity implements AdapterView.OnItemClickListener {
ListView listView;
ImageView imageView;
TextView currentDirText;
TextView numFilesText;
Button backButton;
String rootDir = "DCIM";
String directoryName = rootDir; // Initialize to rootDirectory
SimpleAdapter listAdapter;
int checkInterval = 5000;
Handler updateHandler;
boolean viewingList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewingList = true; // Start out viewing the list
try {
// Set buttons
getWindow().setTitleColor(Color.rgb(65, 183, 216));
backButton = (Button)findViewById(R.id.button1);
backButton.getBackground().setColorFilter(Color.rgb(65, 183, 216), PorterDuff.Mode.SRC_IN);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(directoryName.equals(rootDir)) {
listRootDirectory();
}
else {
int index = directoryName.lastIndexOf("/");
directoryName = directoryName.substring(0, index);
listDirectory(directoryName);
}
}
});
backButton.setEnabled(false); // Disable in root directory
listRootDirectory();
} catch(Exception e) {
Log.e("ERROR", "ERROR: " + e.toString());
e.printStackTrace();
}
updateHandler = new Handler();
startUpdate();
}
We have added a few new member variables to our previous
MainActivity
class.
int checkInterval
, which will set the interval of time (in milliseconds)
between status
checks of the FlashAir.Handler updateHandler
, which will manage the
Runnable
that we will implement in the functions below.boolean viewingList
, which will track whether the user is currently
viewing a content
list or an image.It is worth noting that we have set the root directory to be the "DCIM" folder (line 8). You do not have to set this as your root directory. Since the "DCIM" folder is the location that most digital cameras store photos, it is set as the root directory for this tutorial.
We will leave the rest of the code in MainActivity.java as is. (This should include the functions to set up the content list.)
We will add the code that handles status checking and updating to the
MainActivity.java file. This code should be included inside
class MainActivity
with the other functions we have previously written.
If the user is not currently viewing a content list, there is no need to poll the FlashAir device - the content list will get the most current updates when it loads. However, if the user is currently viewing a content list, we will poll the contents of the FlashAir regularly and display any changes.
In order to determine whether the user is viewing a list, we will override a listener
function to
update the value of the flag variable
viewingList
declared above (on line 13).
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
viewingList = true;
}
else {
viewingList = false;
}
}
public boolean checkIfListView() {
// Check if user is viewing a content list
if(viewingList) {
return true;
}
return false;
}
The variable flag
hasFocus
will be true if the screen showing the content list is currently
being displayed
to the user. Each time the user changes their
View
, the app will be informed. This will facilitate setting the behavior of
the
Runnable
below.
We will use the following CGI command to get the update status of the FlashAir:
command.cgi
with
op=102
http://flashair/command.cgi?op=102
1
if the FlashAir memory has been updated
0
if the memory has not been updated
The CGI command that gets the update status of your FlashAir will only return
1
once. Any future queries before another change is made will return
0
, as the FlashAir memory has not been updated since the last query.
To execute this CGI command, we will reuse the FlashAirRequest.java file from Android Tutorial 3: Downloading Content:
The following functions determine the behavior and frequency for auto refreshing the content list.
public Runnable statusChecker = new Runnable() {
@Override
public void run() {
if (checkIfListView() == true) {
new AsyncTask<String, Void, String>(){
@Override
protected String doInBackground(String... params) {
return FlashAirRequest.getString(params[0]);
}
@Override
protected void onPostExecute(String status) {
if(status.equals("1")) {
// Fetch current contents of FlashAir and display list
listDirectory(directoryName);
}
}
}.execute("http://flashair/command.cgi?op=102");
}
updateHandler.postDelayed(statusChecker, checkInterval);
}
};
public void startUpdate() {
statusChecker.run();
}
public void stopUpdate() {
updateHandler.removeCallbacks(statusChecker);
}
run()
function, which sets the main behavior of the
Runnable class
.updateHandler
assign the
statusChecker
to perform its
run()
function in
checkInterval
milliseconds. Note that this code is executed inside the
run()
function itself. This means that so long as the
updateHandler
does not stop running, each time the
statusChecker
performs its
run()
function, it is assigned to run again in
checkInterval
milliseconds.This file will be identical to the
class ImageViewActivity
from
Android Tutorial 3: Downloading Content.
Please refer to that tutorial for an explanation
of the implementation.
android_tutorial_05.zip (533KB)
All sample code on this page is licensed under BSD 2-Clause License